/*******************************************************************************
 * Creator: Jose Castillo jocasal@gmail.com
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the <organization> nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL DANIEL MURPHY BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ******************************************************************************/
/**
 * Created at 25 Mar, 2011
 */

package packbridge;

/**
 *
 * @author jose
 */
public class Puente {

    float genes[][] = new float[20][10];
    double duracion;
    float distancia;
    int fitness, f_altura;
    int has;
    public static int n_absoluto;
    /*
     * El gen [i][0] es la posicion x
     * [i][1] es y
     * [i][2] es ancho
     * [i][3] es alto
     * [i][4] es angulo
     *
     *
     */

    public Puente(){

        for(int i=0; i<20; i++){
            genes[i][0]=(float) (55 - (Math.random() * 110));
            genes[i][1]=(float) (Math.random() * 90);
            genes[i][2]=(float) (1f + Math.random() * 30);
            genes[i][3]=100.0f/genes[i][2];
            genes[i][4]=(float) (Math.random() * 7);
        }
        duracion=0;
        fitness=0;
        distancia=0;
        f_altura=0;
        n_absoluto++;
        has=n_absoluto;


    }

    public void calcularfitness(){

        // el maximo de tiempo es 30000 ms, el maximo de distancia es de -55 a +55
        // si no llega, es interesante que tarde el mayor tiempo posible en caer.
        // si llega, es interesante que tarde el menor tiempo posible
      double f_tiempo = 0.5*(100-(duracion*100)/30000); // porcentaje sobre 30 segundos de tiempo
      double f_distancia =f_altura+ 1.5*((distancia+55)*100)/100; // porcentaje del camino recorrido
      double f_peso = calcularpeso();

      if(distancia >=51){ // el tiempo es importante, tambien el peso
          fitness = (int) (f_tiempo + f_distancia + f_peso + 50);
      } else { //
          fitness = (int) (f_tiempo + f_distancia);
      }

      System.out.println("FTiempo: "+(int)f_tiempo+" FDistancia:  "+(int)f_distancia+" FP: "+(int)f_peso+" FTotal: "+fitness+" ("+has+") ");

    }


    public double calcularpeso(){

        double f_peso = 0d;
        double p_actual=0;
        for(int i=0; i<20; i++){
            p_actual+=genes[i][2]*genes[i][3];
        }
        f_peso = 100 - (p_actual*100/10000); // 10000 es un peso muy grande que no se debería alcanzar
        return(f_peso); // f_peso inicial deberia ser 80

    }

    public Puente cruzar(Puente aux){ // operacion cruze y mutacion

        /*

         * Se cruzan los genes dependiendo del fitness del padre y la madre
         * El que más fitness tenga tiene los genes más dominantes, el otro los tiene recesivos.
         * Si hay mucha diferencia de fitness, la dominancia máxima es un 90% para que siempre haya algo de cruce
         *
         * Los hijos pueden mutar. Estas mutaciones tendran una cierta tendencia a aumentar de tamaño.
         * Si la variable tendencia se pone a 10, no aumentaran y si se pone más que 10 disminuyen

         */

        Puente hijo = new Puente();
        
        int tendencias;

        float dominantes = (float) Math.abs(this.fitness / (aux.fitness + 0.01));

        if(dominantes > 2) dominantes = 0.9f;
        else dominantes = (float) (dominantes / 2.5);
        
        for(int i=0; i<20; i++){
            for(int j=0; j<5; j++){

                if((Math.random()+dominantes)>1) {
                    hijo.genes[i][j] = this.genes[i][j];
                //  System.out.print("d");
                }
                else { 
                    hijo.genes[i][j] = aux.genes[i][j]; //System.out.print("r");
                }

                if(j==2 || j==3){
                    tendencias=8; //establezco la tendencia a aumentar el tamanyo.
                } else {
                    tendencias=10;
                }
                if(Math.random()<0.05) { // mutacion básica de una parámetro
                    hijo.genes[i][j]+=(5-(Math.random()*tendencias));
                }
                if(Math.random()<0.01) { // crear un nuevo ladrillo de la nada
                 hijo.genes[i][0]=(float) (65 - (Math.random() * 130));
                 hijo.genes[i][1]=(float) (Math.random() * 100);
                 hijo.genes[i][2]=(float) (1f + Math.random() * 30);
                 hijo.genes[i][3]=100.0f/hijo.genes[i][2];
                 hijo.genes[i][4]=(float) (Math.random() * 7);
             }


            }
         }

    return(hijo);
    }

}
